package com.coderside.core;

import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang3.StringUtils;

import com.coderside.core.base.State;
import com.coderside.core.base.Term;

public abstract class ParseCore<T> {
	/**目标输入流对象**/
	private InputStream in;

	/**默认的字符编码**/
	private final String defaultCharset = "UTF-8";

	/**泛型对象的Class类型**/
	private Class<T> destClass;

	/**标签接口的实现类**/
	private Class<? extends State> stateClass;

	public ParseCore(InputStream in, Class<T> clazz, Class<? extends State> classz) {
		this.in = in;
		this.destClass = clazz;
		this.stateClass = classz;
	}

	/**
	 * 解析方法的入口
	 * @return
	 */
	public List<T> startParse() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(in, defaultCharset));
			String line = null;
			List<Term> list = new ArrayList<Term>();
			while ((line = br.readLine()) != null) {
				if (StringUtils.isNotEmpty(line)) {
					doBegin(list);
					parseLine(PreparedLine(line), list);
					doEnd(list);
				}
			}
			return buildDestInstance(list, destClass, stateClass);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return null;

	}

	protected abstract void parseLine(String line, List<Term> list);

	/**
	 * 
	 * @param line
	 * @return
	 */
	protected String PreparedLine(String line) {
		return line.trim();
	}

	protected abstract boolean doBegin(List<Term> list);

	protected abstract boolean doEnd(List<Term> list);

	private List<T> buildDestInstance(List<Term> list, Class<T> clazz, Class<? extends State> stateClass)
			throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		List<T> relist = new ArrayList<T>();
		T instance = null;
		PropertyUtilsBean util = new PropertyUtilsBean();
		for (Term term : list) {
			if (term.getType() == State.BEGIN) {
				instance = clazz.newInstance();
				relist.add(instance);
			} else if (term.getType() == State.END) {
				instance = null;
				continue;
			}
			Field[] fileds = stateClass.getFields();
			for (int i = 0; i < fileds.length; i++) {
				Field f = fileds[i];
				if (f.getName().equals("classes")) {
					continue;
				}
				char c = f.getChar(clazz);
				String name = f.getName().toLowerCase();
				if (term.getType() == c && !name.equals("begin") && !name.equals("end")) {
					PropertyDescriptor p = util.getPropertyDescriptor(instance, name);
					p.getWriteMethod().invoke(instance, term.getContent());
				}
			}
		}
		return relist;
	}
}
